<!DOCTYPE html>
<html style="display: none;" lang="zh">
    <head>
    <meta charset="utf-8">
    <!--
        © Material Theme
        https://github.com/viosey/hexo-theme-material
        Version: 1.5.2 -->
    <script>
        window.materialVersion = "1.5.2"
        // Delete localstorage with these tags
        window.oldVersion = [
            'codestartv1',
            '1.3.4',
            '1.4.0',
            '1.4.0b1',
            '1.5.0'
        ]
    </script>

    <!-- dns prefetch -->
    <meta http-equiv="x-dns-prefetch-control" content="on">


    <link rel="dns-prefetch" href="https://cdn1.lncld.net"/>













    <!-- Meta & Info -->
    <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
    <meta name="renderer" content="webkit">
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">

    <!-- Title -->
    
    <title>
        
            JVM学习03-类加载机制 | 
        
        android开发者
    </title>

    <!-- Favicons -->
    <link rel="icon shortcut" type="image/ico" href="/img/favicon.png">
    <link rel="icon" href="/img/favicon.png">

    <meta name="format-detection" content="telephone=no"/>
    <meta name="description" itemprop="description" content="android开发工程师，学习，记录。">
    <meta name="keywords" content="android,java">
    <meta name="theme-color" content="#0097A7">

    <!-- Disable Fucking Bloody Baidu Tranformation -->
    <meta http-equiv="Cache-Control" content="no-transform" />
    <meta http-equiv="Cache-Control" content="no-siteapp" />

    <!--[if lte IE 9]>
        <link rel="stylesheet" href="/css/ie-blocker.css">

        
            <script src="/js/ie-blocker.zhCN.js"></script>
        
    <![endif]-->

    <!-- Import lsloader -->
    <script>(function(){window.lsloader={jsRunSequence:[],jsnamemap:{},cssnamemap:{}};lsloader.removeLS=function(a){try{localStorage.removeItem(a)}catch(b){}};lsloader.setLS=function(a,c){try{localStorage.setItem(a,c)}catch(b){}};lsloader.getLS=function(a){var c="";try{c=localStorage.getItem(a)}catch(b){c=""}return c};versionString="/*"+(window.materialVersion||"unknownVersion")+"*/";lsloader.clean=function(){try{var b=[];for(var a=0;a<localStorage.length;a++){b.push(localStorage.key(a))}b.forEach(function(e){var f=lsloader.getLS(e);if(window.oldVersion){var d=window.oldVersion.reduce(function(g,h){return g||f.indexOf("/*"+h+"*/")!==-1},false);if(d){lsloader.removeLS(e)}}})}catch(c){}};lsloader.clean();lsloader.load=function(f,a,b,d){if(typeof b==="boolean"){d=b;b=undefined}d=d||false;b=b||function(){};var e;e=this.getLS(f);if(e&&e.indexOf(versionString)===-1){this.removeLS(f);this.requestResource(f,a,b,d);return}if(e){var c=e.split(versionString)[0];if(c!=a){console.log("reload:"+a);this.removeLS(f);this.requestResource(f,a,b,d);return}e=e.split(versionString)[1];if(d){this.jsRunSequence.push({name:f,code:e});this.runjs(a,f,e)}else{document.getElementById(f).appendChild(document.createTextNode(e));b()}}else{this.requestResource(f,a,b,d)}};lsloader.requestResource=function(b,e,a,c){var d=this;if(c){this.iojs(e,b,function(h,f,g){d.setLS(f,h+versionString+g);d.runjs(h,f,g)})}else{this.iocss(e,b,function(f){document.getElementById(b).appendChild(document.createTextNode(f));d.setLS(b,e+versionString+f)},a)}};lsloader.iojs=function(d,b,g){var a=this;a.jsRunSequence.push({name:b,code:""});try{var f=new XMLHttpRequest();f.open("get",d,true);f.onreadystatechange=function(){if(f.readyState==4){if((f.status>=200&&f.status<300)||f.status==304){if(f.response!=""){g(d,b,f.response);return}}a.jsfallback(d,b)}};f.send(null)}catch(c){a.jsfallback(d,b)}};lsloader.iocss=function(f,c,h,a){var b=this;try{var g=new XMLHttpRequest();g.open("get",f,true);g.onreadystatechange=function(){if(g.readyState==4){if((g.status>=200&&g.status<300)||g.status==304){if(g.response!=""){h(g.response);a();return}}b.cssfallback(f,c,a)}};g.send(null)}catch(d){b.cssfallback(f,c,a)}};lsloader.iofonts=function(f,c,h,a){var b=this;try{var g=new XMLHttpRequest();g.open("get",f,true);g.onreadystatechange=function(){if(g.readyState==4){if((g.status>=200&&g.status<300)||g.status==304){if(g.response!=""){h(g.response);a();return}}b.cssfallback(f,c,a)}};g.send(null)}catch(d){b.cssfallback(f,c,a)}};lsloader.runjs=function(f,c,e){if(!!c&&!!e){for(var b in this.jsRunSequence){if(this.jsRunSequence[b].name==c){this.jsRunSequence[b].code=e}}}if(!!this.jsRunSequence[0]&&!!this.jsRunSequence[0].code&&this.jsRunSequence[0].status!="failed"){var a=document.createElement("script");a.appendChild(document.createTextNode(this.jsRunSequence[0].code));a.type="text/javascript";document.getElementsByTagName("head")[0].appendChild(a);this.jsRunSequence.shift();if(this.jsRunSequence.length>0){this.runjs()}}else{if(!!this.jsRunSequence[0]&&this.jsRunSequence[0].status=="failed"){var d=this;var a=document.createElement("script");a.src=this.jsRunSequence[0].path;a.type="text/javascript";this.jsRunSequence[0].status="loading";a.onload=function(){d.jsRunSequence.shift();if(d.jsRunSequence.length>0){d.runjs()}};document.body.appendChild(a)}}};lsloader.tagLoad=function(b,a){this.jsRunSequence.push({name:a,code:"",path:b,status:"failed"});this.runjs()};lsloader.jsfallback=function(c,b){if(!!this.jsnamemap[b]){return}else{this.jsnamemap[b]=b}for(var a in this.jsRunSequence){if(this.jsRunSequence[a].name==b){this.jsRunSequence[a].code="";this.jsRunSequence[a].status="failed";this.jsRunSequence[a].path=c}}this.runjs()};lsloader.cssfallback=function(e,c,b){if(!!this.cssnamemap[c]){return}else{this.cssnamemap[c]=1}var d=document.createElement("link");d.type="text/css";d.href=e;d.rel="stylesheet";d.onload=d.onerror=b;var a=document.getElementsByTagName("script")[0];a.parentNode.insertBefore(d,a)};lsloader.runInlineScript=function(c,b){var a=document.getElementById(b).innerText;this.jsRunSequence.push({name:c,code:a});this.runjs()}})();</script>

    <!-- Import queue -->
    <script>function Queue(){this.dataStore=[];this.offer=b;this.poll=d;this.execNext=a;this.debug=false;this.startDebug=c;function b(e){if(this.debug){console.log("Offered a Queued Function.")}if(typeof e==="function"){this.dataStore.push(e)}else{console.log("You must offer a function.")}}function d(){if(this.debug){console.log("Polled a Queued Function.")}return this.dataStore.shift()}function a(){var e=this.poll();if(e!==undefined){if(this.debug){console.log("Run a Queued Function.")}e()}}function c(){this.debug=true}}var queue=new Queue();</script>

    <!-- Import CSS -->
    
        <style id="material_css"></style><script>if(typeof window.lsLoadCSSMaxNums === "undefined")window.lsLoadCSSMaxNums = 0;window.lsLoadCSSMaxNums++;lsloader.load("material_css","/css/material.min.css?Z7a72R1E4SxzBKR/WGctOA==",function(){if(typeof window.lsLoadCSSNums === "undefined")window.lsLoadCSSNums = 0;window.lsLoadCSSNums++;if(window.lsLoadCSSNums == window.lsLoadCSSMaxNums)document.documentElement.style.display="";}, false)</script>
        <style id="style_css"></style><script>if(typeof window.lsLoadCSSMaxNums === "undefined")window.lsLoadCSSMaxNums = 0;window.lsLoadCSSMaxNums++;lsloader.load("style_css","/css/style.min.css?NKhlKQkXw/c66TR5p4wO+w==",function(){if(typeof window.lsLoadCSSNums === "undefined")window.lsLoadCSSNums = 0;window.lsLoadCSSNums++;if(window.lsLoadCSSNums == window.lsLoadCSSMaxNums)document.documentElement.style.display="";}, false)</script>

        

    

    

    <!-- Config CSS -->

<!-- Other Styles -->
<style>
  body, html {
    font-family: Roboto, "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
    overflow-x: hidden !important;
  }
  
  code {
    font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
  }

  a {
    color: #00838F;
  }

  .mdl-card__media,
  #search-label,
  #search-form-label:after,
  #scheme-Paradox .hot_tags-count,
  #scheme-Paradox .sidebar_archives-count,
  #scheme-Paradox .sidebar-colored .sidebar-header,
  #scheme-Paradox .sidebar-colored .sidebar-badge{
    background-color: #0097A7 !important;
  }

  /* Sidebar User Drop Down Menu Text Color */
  #scheme-Paradox .sidebar-colored .sidebar-nav>.dropdown>.dropdown-menu>li>a:hover,
  #scheme-Paradox .sidebar-colored .sidebar-nav>.dropdown>.dropdown-menu>li>a:focus {
    color: #0097A7 !important;
  }

  #post_entry-right-info,
  .sidebar-colored .sidebar-nav li:hover > a,
  .sidebar-colored .sidebar-nav li:hover > a i,
  .sidebar-colored .sidebar-nav li > a:hover,
  .sidebar-colored .sidebar-nav li > a:hover i,
  .sidebar-colored .sidebar-nav li > a:focus i,
  .sidebar-colored .sidebar-nav > .open > a,
  .sidebar-colored .sidebar-nav > .open > a:hover,
  .sidebar-colored .sidebar-nav > .open > a:focus,
  #ds-reset #ds-ctx .ds-ctx-entry .ds-ctx-head a {
    color: #0097A7 !important;
  }

  .toTop {
    background: #757575 !important;
  }

  .material-layout .material-post>.material-nav,
  .material-layout .material-index>.material-nav,
  .material-nav a {
    color: #757575;
  }

  #scheme-Paradox .MD-burger-layer {
    background-color: #757575;
  }

  #scheme-Paradox #post-toc-trigger-btn {
    color: #757575;
  }

  .post-toc a:hover {
    color: #00838F;
    text-decoration: underline;
  }

</style>


<!-- Theme Background Related-->

    <style>
      body{
        background-color: #F5F5F5;
      }

      /* blog_info bottom background */
      #scheme-Paradox .material-layout .something-else .mdl-card__supporting-text{
        background-color: #fff;
      }
    </style>




<!-- Fade Effect -->

    <style>
      .fade {
        transition: all 800ms linear;
        -webkit-transform: translate3d(0,0,0);
        -moz-transform: translate3d(0,0,0);
        -ms-transform: translate3d(0,0,0);
        -o-transform: translate3d(0,0,0);
        transform: translate3d(0,0,0);
        opacity: 1;
      }

      .fade.out{
        opacity: 0;
      }
    </style>


<!-- Import Font -->
<!-- Import Roboto -->

    <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet">


<!-- Import Material Icons -->


    <style id="material_icons"></style><script>if(typeof window.lsLoadCSSMaxNums === "undefined")window.lsLoadCSSMaxNums = 0;window.lsLoadCSSMaxNums++;lsloader.load("material_icons","/css/material-icons.css?pqhB/Rd/ab0H2+kZp0RDmw==",function(){if(typeof window.lsLoadCSSNums === "undefined")window.lsLoadCSSNums = 0;window.lsLoadCSSNums++;if(window.lsLoadCSSNums == window.lsLoadCSSMaxNums)document.documentElement.style.display="";}, false)</script>




    <!-- Import jQuery -->
    
        <script>lsloader.load("jq_js","/js/jquery.min.js?qcusAULNeBksqffqUM2+Ig==", true)</script>
    

    <!-- WebAPP Icons -->
    <meta name="mobile-web-app-capable" content="yes">
    <meta name="application-name" content="android开发者">
    <meta name="msapplication-starturl" content="http://www.xincc.top/2017/03/18/java/JVM学习03-类加载机制/">
    <meta name="msapplication-navbutton-color" content="#0097A7">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-title" content="android开发者">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <link rel="apple-touch-icon" href="/img/favicon.png">

    <!-- Site Verification -->
    
    

    <!-- RSS -->
    

    <!-- The Open Graph protocol -->
    <meta property="og:url" content="http://www.xincc.top/2017/03/18/java/JVM学习03-类加载机制/">
    <meta property="og:type" content="blog">
    <meta property="og:title" content="JVM学习03-类加载机制 | android开发者">
    <meta property="og:image" content="/img/favicon.png">
    <meta property="og:description" content="android开发工程师，学习，记录。">
    <meta property="og:article:tag" content="java"> 

    
        <meta property="article:published_time" content="Sat Mar 18 2017 18:00:34 GMT+0800">
        <meta property="article:modified_time" content="Sun May 06 2018 16:42:00 GMT+0800">
    

    <!-- The Twitter Card protocol -->
    <meta name="twitter:card" content="summary_large_image">

    <!-- Add canonical link for SEO -->
    
        <link rel="canonical" href="http://www.xincc.top/2017/03/18/java/JVM学习03-类加载机制/index.html" />
    

    <!-- Structured-data for SEO -->
    
        


<script type="application/ld+json">
{
    "@context": "https://schema.org",
    "@type": "BlogPosting",
    "mainEntityOfPage": "http://www.xincc.top/2017/03/18/java/JVM学习03-类加载机制/index.html",
    "headline": "JVM学习03-类加载机制",
    "datePublished": "Sat Mar 18 2017 18:00:34 GMT+0800",
    "dateModified": "Sun May 06 2018 16:42:00 GMT+0800",
    "author": {
        "@type": "Person",
        "name": "xinwii",
        "image": {
            "@type": "ImageObject",
            "url": "/img/avatar.png"
        },
        "description": "Hi, nice to meet you"
    },
    "publisher": {
        "@type": "Organization",
        "name": "android开发者",
        "logo": {
            "@type":"ImageObject",
            "url": "/img/favicon.png"
        }
    },
    "keywords": ",javaandroid",
    "description": "android开发工程师，学习，记录。",
}
</script>


    

    <!-- Analytics -->
    
    
        <script>
    var _hmt = _hmt || [];
    (function() {var hm = document.createElement('script');
    hm.src = 'https://hm.baidu.com/hm.js?ee8e425850499b806260824b0147ff70';
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(hm, s);
    })();
</script>
    
    

    <!-- Custom Head -->
    

</head>


    
        <body id="scheme-Paradox" class="lazy">
            <div class="material-layout  mdl-js-layout has-drawer is-upgraded">
                

                <!-- Main Container -->
                <main class="material-layout__content" id="main">

                    <!-- Top Anchor -->
                    <div id="top"></div>

                    
                        <!-- Hamburger Button -->
                        <button class="MD-burger-icon sidebar-toggle">
                            <span class="MD-burger-layer"></span>
                        </button>
                    

                    <!-- Post TOC -->

    
    <!-- Back Button -->
    <!--
    <div class="material-back" id="backhome-div" tabindex="0">
        <a class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon"
           href="#" onclick="window.history.back();return false;"
           target="_self"
           role="button"
           data-upgraded=",MaterialButton,MaterialRipple">
            <i class="material-icons" role="presentation">arrow_back</i>
            <span class="mdl-button__ripple-container">
                <span class="mdl-ripple"></span>
            </span>
        </a>
    </div>
    -->


    <!-- Left aligned menu below button -->
    
    
    <button id="post-toc-trigger-btn"
        class="mdl-button mdl-js-button mdl-button--icon">
        <i class="material-icons">format_list_numbered</i>
    </button>

    <ul class="post-toc-wrap mdl-menu mdl-menu--bottom-left mdl-js-menu mdl-js-ripple-effect" for="post-toc-trigger-btn" style="max-height:80vh; overflow-y:scroll;">
        <ol class="post-toc"><li class="post-toc-item post-toc-level-1"><a class="post-toc-link" href="#JVM学习03-类加载机制"><span class="post-toc-number">1.</span> <span class="post-toc-text">JVM学习03-类加载机制</span></a></li><li class="post-toc-item post-toc-level-1"><a class="post-toc-link" href="#1-类加载器简介"><span class="post-toc-number">2.</span> <span class="post-toc-text">1. 类加载器简介</span></a></li><li class="post-toc-item post-toc-level-1"><a class="post-toc-link" href="#2-class加载验证流程"><span class="post-toc-number">3.</span> <span class="post-toc-text">2. class加载验证流程</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-1-类加载"><span class="post-toc-number">3.1.</span> <span class="post-toc-text">2.1 类加载</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-2-链接"><span class="post-toc-number">3.2.</span> <span class="post-toc-text">2.2 链接</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-3-初始化"><span class="post-toc-number">3.3.</span> <span class="post-toc-text">2.3 初始化</span></a></li></ol></li><li class="post-toc-item post-toc-level-1"><a class="post-toc-link" href="#3-类的加载器"><span class="post-toc-number">4.</span> <span class="post-toc-text">3. 类的加载器</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#3-1-父类委托机制"><span class="post-toc-number">4.1.</span> <span class="post-toc-text">3.1 父类委托机制</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#3-2-ClassLoader中的一些方法"><span class="post-toc-number">4.2.</span> <span class="post-toc-text">3.2 ClassLoader中的一些方法</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#3-3-父类委托的缺陷和解决"><span class="post-toc-number">4.3.</span> <span class="post-toc-text">3.3 父类委托的缺陷和解决</span></a></li></ol></li><li class="post-toc-item post-toc-level-1"><a class="post-toc-link" href="#4-自定义类加载器"><span class="post-toc-number">5.</span> <span class="post-toc-text">4. 自定义类加载器</span></a></li></ol>
    </ul>
    




<!-- Layouts -->

    <!-- Post Module -->
    <div class="material-post_container">

        <div class="material-post mdl-grid">
            <div class="mdl-card mdl-shadow--4dp mdl-cell mdl-cell--12-col">

                <!-- Post Header(Thumbnail & Title) -->
                
    <!-- Paradox Post Header -->
    
        
            <!-- Random Thumbnail -->
            <div class="post_thumbnail-random mdl-card__media mdl-color-text--grey-50">
            <script type="text/ls-javascript" id="post-thumbnail-script">
    var randomNum = Math.floor(Math.random() * 19 + 1);

    $('.post_thumbnail-random').attr('data-original', '/img/random/material-' + randomNum + '.png');
    $('.post_thumbnail-random').addClass('lazy');
</script>

        
    
            <p class="article-headline-p">
                JVM学习03-类加载机制
            </p>
        </div>





                
                    <!-- Paradox Post Info -->
                    <div class="mdl-color-text--grey-700 mdl-card__supporting-text meta">

    <!-- Author Avatar -->
    <div id="author-avatar">
        <img src="/img/avatar.png" width="44px" height="44px" alt="Author Avatar"/>
    </div>
    <!-- Author Name & Date -->
    <div>
        <strong>xinwii</strong>
        <span>3月 18, 2017</span>
    </div>

    <div class="section-spacer"></div>

    <!-- Favorite -->
    <!--
        <button id="article-functions-like-button" class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon btn-like">
            <i class="material-icons" role="presentation">favorite</i>
            <span class="visuallyhidden">favorites</span>
        </button>
    -->

    <!-- Qrcode -->
    

    <!-- Tags (bookmark) -->
    
    <button id="article-functions-viewtags-button" class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon">
        <i class="material-icons" role="presentation">bookmark</i>
        <span class="visuallyhidden">bookmark</span>
    </button>
    <ul class="mdl-menu mdl-menu--bottom-right mdl-js-menu mdl-js-ripple-effect" for="article-functions-viewtags-button">
        <li class="mdl-menu__item">
        <a class="post_tag-link" href="/tags/java/">java</a>
    </ul>
    

    <!-- Share -->
    
        <button id="article-fuctions-share-button" class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon">
    <i class="material-icons" role="presentation">share</i>
    <span class="visuallyhidden">share</span>
</button>
<ul class="mdl-menu mdl-menu--bottom-right mdl-js-menu mdl-js-ripple-effect" for="article-fuctions-share-button">
    
    <!-- Leancloud Views -->
        <a class="post_share-link" href="#">
            <li class="mdl-menu__item">
                <span id="/2017/03/18/java/JVM学习03-类加载机制/" class="leancloud-views_num" data-flag-title="JVM学习03-类加载机制">
     &nbsp;浏览量
</span>

            </li>
        </a>
    

    

    <!-- Share Weibo -->
    
        <a class="post_share-link" href="http://service.weibo.com/share/share.php?appkey=&title=JVM学习03-类加载机制&url=http://www.xincc.top/2017/03/18/java/JVM学习03-类加载机制/index.html&pic=http://www.xincc.top/img/favicon.png&searchPic=false&style=simple" target="_blank">
            <li class="mdl-menu__item">
                分享到微博
            </li>
        </a>
    

    <!-- Share Twitter -->
    
        <a class="post_share-link" href="https://twitter.com/intent/tweet?text=JVM学习03-类加载机制&url=http://www.xincc.top/2017/03/18/java/JVM学习03-类加载机制/index.html&via=xinwii" target="_blank">
            <li class="mdl-menu__item">
                分享到 Twitter
            </li>
        </a>
    

    <!-- Share Facebook -->
    
        <a class="post_share-link" href="https://www.facebook.com/sharer/sharer.php?u=http://www.xincc.top/2017/03/18/java/JVM学习03-类加载机制/index.html" target="_blank">
            <li class="mdl-menu__item">
                分享到 Facebook
            </li>
        </a>
    

    <!-- Share Google+ -->
    
        <a class="post_share-link" href="https://plus.google.com/share?url=http://www.xincc.top/2017/03/18/java/JVM学习03-类加载机制/index.html" target="_blank">
            <li class="mdl-menu__item">
                分享到 Google+
            </li>
        </a>
    

    <!-- Share LinkedIn -->
    

    <!-- Share QQ -->
    

    <!-- Share Telegram -->
    
</ul>

    
</div>

                

                <!-- Post Content -->
                <div id="post-content" class="mdl-color-text--grey-700 mdl-card__supporting-text fade out">
    
        <p>[TOC]</p>
<h1 id="JVM学习03-类加载机制"><a href="#JVM学习03-类加载机制" class="headerlink" title="JVM学习03-类加载机制"></a>JVM学习03-类加载机制</h1><h1 id="1-类加载器简介"><a href="#1-类加载器简介" class="headerlink" title="1. 类加载器简介"></a>1. 类加载器简介</h1><p>之前有讲述过 JVM 的启动流程，在JVM找到配置文件对JVM进行初始化的时候，将会生成最基础的类加载器（c/c++语言编写）BootStrap。<br>在说classLoader前先看一段程序：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">ClassLoader classLoader = <span class="keyword">this</span>.getClass().getClassLoader();</span><br><span class="line">System.out.println(<span class="string">"当前的ClassLoader : "</span> + classLoader);</span><br><span class="line">System.out.println(<span class="string">"父ClassLoader : "</span> + classLoader.getParent());</span><br><span class="line">System.out.println(<span class="string">"曾ClassLoader : "</span> + classLoader.getParent().getParent());</span><br><span class="line"></span><br><span class="line"><span class="comment">// 结果：</span></span><br><span class="line"><span class="comment">// 当前的ClassLoader : sun.misc.Launcher$AppClassLoader@2a788b76</span></span><br><span class="line"><span class="comment">// 父ClassLoader : sun.misc.Launcher$ExtClassLoader@500c05c2</span></span><br><span class="line"><span class="comment">// 曾ClassLoader : null</span></span><br></pre></td></tr></table></figure>
<p>可以看出来jdk默认当前应用程序的classLoader为AppClassLoader，然后往上的父ClassLoader是ExtClassLoader，然后是null。</p>
<p>那么为什么最顶层的是null，这也就是BootStrap并不是java语言编写的，而是一个顶级的ClassLoader。当JVM启动Bootrap之后，Bootrap就会随之启动ExtClassLoader和AppClassLoader，并完成父子继承关系，最后由AppClassLoader加载主类的字节码，寻找到main函数进行启动。大致如图：</p>
<p><img src="http://img.blog.csdn.net/20160108124018036" alt="这里写图片描述"></p>
<ol>
<li>BootStrapClassLoader：jre路径/lib/rt.jar中的字节码，或者通过 -Xbootclasspath 参数指定路径的下的字节码。</li>
<li>ExtClassLoader ： jre路径/lib/ext目录下 *.jar 的字节码。</li>
<li>AppClassLoader： 加载用户classpath下的字节码。</li>
</ol>
<p>除了 BootStrapClassLoader 不能直接被程序员使用外，其他的类加载器都能被程序使用和修改。</p>
<h1 id="2-class加载验证流程"><a href="#2-class加载验证流程" class="headerlink" title="2. class加载验证流程"></a>2. class加载验证流程</h1><p>要让主类中的main函数运行，当然少不了的就是字节码（class）的加载。这个也是class装载验证流程中的<code>第一步类加载</code>。然后<code>第二步是链接</code>，<code>最后是进行初始化</code>。</p>
<h2 id="2-1-类加载"><a href="#2-1-类加载" class="headerlink" title="2.1 类加载"></a>2.1 类加载</h2><p>首先肯定是读取class文件的二进制流。由于Class等类的信息的存储在方法区中的，所以进而转化为方法区的数据结构，为了能够被使用，最后在java堆中生成代表这个字节码的java.lang.Class对象。</p>
<h2 id="2-2-链接"><a href="#2-2-链接" class="headerlink" title="2.2 链接"></a>2.2 链接</h2><p>在链接中又分为验证，准备和解析等几个步骤。</p>
<p>(1)验证：验证字节码肯定是为了确保字节码的正确性，比如文件是否以<code>0xCAFEBABE</code>开头，版本是否正确等等。这个过程需要对字节码中的内容做大量的验证，诸如文件的格式，元数据，字节码验证，符合引用验证等等。<br>(2)准备：之前在讲述java成员初始化一节中提到，在初始化之后首先需要对类进行加载。所以在这一步就是对类中的成员进行内存的分配。例如对于</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> i = <span class="number">1</span>;</span><br></pre></td></tr></table></figure>
<p>先对i进行内存的分配，然后再赋上初始值为0。注意是准备阶段是0，<strong>然后准备阶段完成之后的类的初始化中</strong>，才会执行语句赋值为1。</p>
<p>这里在补充一个知识点：编译时常量和运行时常量。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">static</span> <span class="keyword">int</span> i = <span class="number">2</span>;</span><br><span class="line"><span class="comment">// 对于final static类型, 在准备阶段就会被赋值为2.</span></span><br><span class="line"><span class="comment">// 因为i的值不能修改, 所以在编译的时候, i的值就已经确认了</span></span><br><span class="line"><span class="comment">// 所以对于final修饰变量称为编译时常量.</span></span><br><span class="line"><span class="comment">// ------- 举个面试题</span></span><br><span class="line"><span class="keyword">byte</span> b1=<span class="number">1</span>,b2=<span class="number">2</span>,b3,b6; </span><br><span class="line"><span class="keyword">final</span> <span class="keyword">byte</span> b4=<span class="number">4</span>,b5=<span class="number">6</span>; </span><br><span class="line">b6=b4+b5; </span><br><span class="line">b3=(b1+b2); </span><br><span class="line">System.out.println(b3+b6);</span><br><span class="line"><span class="comment">// 该题目在第四行会报错，原因是(b1 + b2) 会自动将类型提升为int型</span></span><br><span class="line"><span class="comment">// 那为毛第三行不报错呢? 原因是b4和b5带有final类型, 编译器会立即知道他们的值，然后对b4+b5进行优化, 代码其实就变成了</span></span><br><span class="line"><span class="comment">// b6 = 10; 所以不会报错.</span></span><br></pre></td></tr></table></figure>
<p>(3)解析：在解析阶段主要是将符号引用转换为直接引用。符号引用简单来说就是一个字符串，而这个字符串所引用内容的信息必须能够唯一标识一个类、字段和方法等。比如对于一个类的符号引用，必须给出类的全名，如java.lang.Object。而直接引用就是引用某个对象的一个指针或者地址偏移量，是一定存在的引用对象。</p>
<h2 id="2-3-初始化"><a href="#2-3-初始化" class="headerlink" title="2.3 初始化"></a>2.3 初始化</h2><p>类的初始化，包括static的初始化和非static的初始化，详细参考：<a href="http://patamon.me/icemimosa/Java/java%E5%8F%98%E9%87%8F%E7%9A%84%E5%88%9D%E5%A7%8B%E5%8C%96%E9%A1%BA%E5%BA%8F/" target="_blank" rel="noopener">java变量的初始化顺序</a></p>
<h1 id="3-类的加载器"><a href="#3-类的加载器" class="headerlink" title="3. 类的加载器"></a>3. 类的加载器</h1><h2 id="3-1-父类委托机制"><a href="#3-1-父类委托机制" class="headerlink" title="3.1 父类委托机制"></a>3.1 父类委托机制</h2><p>由上面的类加载器的继承结构可以看出，每个加载器都负责加载自己负责的区域。从java1.2开始，类加载的过程引入了父类委托的机制，这种机制更好的保证了java平台的安全性。<br><strong>原则：类的寻找是由下往上的，类的加载是由上往下的。</strong></p>
<p>假设平台只有Bootstrap，ExtClassLoader和AppClassLoader三个加载器，当用户类路径下一个类如MyTest类被加载的时候，AppClassLoader首先查看该类是否已经被加载了，如果有就返回该类的字节码，否则询问父亲ExtClassLoader是否已经加载了。同样ExtClassLoader先查看是否自己已经加载了MyTest，如果有就返回，否则继续问Bootstrap。当然由于是在类路径下，Bootstrap也没有加载，也没有父亲可问。这个时候，他就会查看自己是否能够加载MyTest，当然由于在用户路径下（所以不能加载），然后告诉ExtClassLoader说我不能加载。然后同样ExtClassLoader也不能加载并告诉AppClassLoader也不能加载，最后AppClassLoader在查看该类的路径，对该类进行加载。这个就是类的寻找是由下往上的，加载是由上往下的。</p>
<p>实现父类委托的关键代码（ClassLoader）：</p>
<p><img src="http://img.blog.csdn.net/20160108124148506" alt="这里写图片描述"></p>
<h2 id="3-2-ClassLoader中的一些方法"><a href="#3-2-ClassLoader中的一些方法" class="headerlink" title="3.2 ClassLoader中的一些方法"></a>3.2 ClassLoader中的一些方法</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 载入并返回一个Class</span></span><br><span class="line"><span class="keyword">public</span> Class&lt;?&gt; loadClass(String name) <span class="keyword">throws</span> ClassNotFoundException</span><br><span class="line"></span><br><span class="line"><span class="comment">// 定义一个类，不公开调用, jdk提供加载字节码的唯一入口，不能覆盖</span></span><br><span class="line"><span class="comment">// 可从磁盘读取字节码</span></span><br><span class="line"><span class="keyword">protected</span> <span class="keyword">final</span> Class&lt;?&gt; defineClass(<span class="keyword">byte</span>[] b, <span class="keyword">int</span> off, <span class="keyword">int</span> len)</span><br><span class="line"></span><br><span class="line"><span class="comment">// loadClass回调该方法，自定义ClassLoader的推荐做法</span></span><br><span class="line"><span class="keyword">protected</span> Class&lt;?&gt; findClass(String name) <span class="keyword">throws</span> ClassNotFoundException</span><br><span class="line"></span><br><span class="line"><span class="comment">// 寻找已经加载的类</span></span><br><span class="line"><span class="keyword">protected</span> <span class="keyword">final</span> Class&lt;?&gt; findLoadedClass(String name)</span><br></pre></td></tr></table></figure>
<h2 id="3-3-父类委托的缺陷和解决"><a href="#3-3-父类委托的缺陷和解决" class="headerlink" title="3.3 父类委托的缺陷和解决"></a>3.3 父类委托的缺陷和解决</h2><p>由于类加载器父类委托的存在，就会导致父类加载器无法加载子类加载器所加载的类。换句话说，比如Java的<strong>SPI机制(Service Provider Interface<br> )</strong>中，类的接口是定义在rt.jar包中的，而具体的实现是由指定厂商提供，是定义的AppClassLoader中的，如果rt.jar中有一个类需要返回该接口的一个实现，那么就需要加载获取AppClassLoader中这个接口实现类的字节码。<br>按照父类委托机制，rt.jar的类加载器是无法访问子加载器加载的字节码的，那么该如何解决。<br>这个就引入了一个<strong>线程上下文类加载器</strong>的概念，基本思想是给顶层类加载传入底层类加载器的实例。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 设置线程上下文类加载器</span></span><br><span class="line">Thread.setContextClassLoader(ClassLoader cl)</span><br><span class="line"><span class="comment">// 获取线程上下文类加载器</span></span><br><span class="line">Thread.getContextClassLoader()</span><br></pre></td></tr></table></figure>
<p>这样，顶层的加载器通过线程的上下文就能访问到底层类加载，从而可以获取底层加载器所加载的字节码。<br>打破这种默认的父类委托机制模式的应用如Tomcat的WebappClassLoader，OSGi的ClassLoader根据需要自由加载Class等等。<br>由于父类委托的核心代码是在loadClass方法中实现的，所以当然也可以通过覆盖loadClass方法来打破父类委托的机制，比如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">protected</span> <span class="keyword">synchronized</span> Class&lt;?&gt; loadClass(String name, <span class="keyword">boolean</span> resolve) <span class="keyword">throws</span> ClassNotFoundException &#123;</span><br><span class="line">    <span class="comment">// First, check if the class has already been loaded</span></span><br><span class="line">    <span class="comment">// 在findClass中实现类的定义defineClass装载</span></span><br><span class="line">    Class re=findClass(name);</span><br><span class="line">    <span class="keyword">if</span>(re==<span class="keyword">null</span>)&#123;</span><br><span class="line">        System.out.println(“无法载入类:”+name+“ 需要请求父加载器<span class="string">");</span></span><br><span class="line"><span class="string">        return super.loadClass(name,resolve);</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    return re;</span></span><br><span class="line"><span class="string">&#125;</span></span><br></pre></td></tr></table></figure>
<h1 id="4-自定义类加载器"><a href="#4-自定义类加载器" class="headerlink" title="4. 自定义类加载器"></a>4. 自定义类加载器</h1><p>通过自定义类加载器我们可以对手动生成的字节码进行加载，可以实现热部署等等一些功能。<br>相信大家经常使用tomcat的热部署，那么关于自定义类的热部署可参照博文：</p>
<p><a href="http://blog.csdn.net/ozwarld/article/details/7440868" target="_blank" rel="noopener">《Java Class热替换》</a></p>
<p>其他博文参考：<br><a href="http://my.oschina.net/aminqiao/blog/262601" target="_blank" rel="noopener">《Java Classloader机制解析》</a><br><a href="http://tyrion.iteye.com/blog/1958814" target="_blank" rel="noopener">《翻译：走出类加载器迷宫》</a> </p>

        
    

    
</div>


                

                <!-- Post Comments -->
                
                    
    <div id="comment" style='padding:10px;' class="vcomment"></div>
<script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
<script src="//unpkg.com/valine/dist/Valine.min.js"></script>
<script>
    var GUEST_INFO = ['nick','mail','link'];
    var guest_info = 'nick,mail,link'.split(',').filter(function(item){
        return GUEST_INFO.indexOf(item) > -1
    });
    var notify = 'false' == true;
    var verify = 'false' == true;
    new Valine({
        el: '.vcomment',
        notify: notify,
        verify: verify,
        appId: "vEOpfYrMUTPxez4tOTNQJv9A-gzGzoHsz",
        appKey: "qlbEzWd9EJ3vHa07eHpWPIVU",
        placeholder: "Just go go",
        pageSize:'10',
        avatar:'identicon',
        lang:'zh-cn'
    });
</script>

                
            </div>

            <!-- Post Prev & Next Nav -->
            <nav class="material-nav mdl-color-text--grey-50 mdl-cell mdl-cell--12-col">
    <!-- Prev Nav -->
    
        <a href="/2017/03/24/java/JVM学习04-class字节码的结构/" id="post_nav-newer" class="prev-content">
            <button class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon mdl-color--white mdl-color-text--grey-900" role="presentation">
                <i class="material-icons">arrow_back</i>
            </button>
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            新篇
        </a>
    

    <!-- Section Spacer -->
    <div class="section-spacer"></div>

    <!-- Next Nav -->
    
        <a href="/2017/03/15/java/JVM学习02-GC算法与种类/" id="post_nav-older" class="next-content">
            旧篇
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            <button class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon mdl-color--white mdl-color-text--grey-900" role="presentation">
                <i class="material-icons">arrow_forward</i>
            </button>
        </a>
    
</nav>

        </div>
    </div>



                    
                        <!-- Overlay For Active Sidebar -->
<div class="sidebar-overlay"></div>

<!-- Material sidebar -->
<aside id="sidebar" class="sidebar sidebar-colored sidebar-fixed-left" role="navigation">
    <div id="sidebar-main">
        <!-- Sidebar Header -->
        <div class="sidebar-header header-cover" style="background-image: url(/img/sidebar_header.png);">
    <!-- Top bar -->
    <div class="top-bar"></div>

    <!-- Sidebar toggle button -->
    <button type="button" class="sidebar-toggle mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon" style="display: initial;" data-upgraded=",MaterialButton,MaterialRipple">
        <i class="material-icons">clear_all</i>
        <span class="mdl-button__ripple-container">
            <span class="mdl-ripple">
            </span>
        </span>
    </button>

    <!-- Sidebar Avatar -->
    <div class="sidebar-image">
        <img src="/img/avatar.png" alt="xinwii's avatar">
    </div>

    <!-- Sidebar Email -->
    <a data-toggle="dropdown" class="sidebar-brand" href="#settings-dropdown">
        mestic@foxmail.com
        <b class="caret"></b>
    </a>
</div>


        <!-- Sidebar Navigation  -->
        <ul class="nav sidebar-nav">
    <!-- User dropdown  -->
    <li class="dropdown">
        <ul id="settings-dropdown" class="dropdown-menu">
            
                <li>
                    <a href="mailto:mestic@foxmail.com" target="_blank" title="Email Me">
                        
                            <i class="material-icons sidebar-material-icons sidebar-indent-left1pc-element">email</i>
                        
                        Email Me
                    </a>
                </li>
            
        </ul>
    </li>

    <!-- Homepage -->
    
        <li id="sidebar-first-li">
            <a href="/">
                
                    <i class="material-icons sidebar-material-icons">home</i>
                
                主页
            </a>
        </li>
        
    

    <!-- Archives  -->
    
        <li class="dropdown">
            <a href="#" class="ripple-effect dropdown-toggle" data-toggle="dropdown">
                
                    <i class="material-icons sidebar-material-icons">inbox</i>
                
                    归档
                <b class="caret"></b>
            </a>
            <ul class="dropdown-menu">
            <li>
                <a class="sidebar_archives-link" href="/archives/2018/06/">六月 2018<span class="sidebar_archives-count">2</span></a></li><li><a class="sidebar_archives-link" href="/archives/2018/05/">五月 2018<span class="sidebar_archives-count">2</span></a></li><li><a class="sidebar_archives-link" href="/archives/2018/04/">四月 2018<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/archives/2018/01/">一月 2018<span class="sidebar_archives-count">2</span></a></li><li><a class="sidebar_archives-link" href="/archives/2017/08/">八月 2017<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/archives/2017/06/">六月 2017<span class="sidebar_archives-count">3</span></a></li><li><a class="sidebar_archives-link" href="/archives/2017/04/">四月 2017<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/archives/2017/03/">三月 2017<span class="sidebar_archives-count">8</span></a></li><li><a class="sidebar_archives-link" href="/archives/2017/01/">一月 2017<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/archives/2016/12/">十二月 2016<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/archives/2016/01/">一月 2016<span class="sidebar_archives-count">6</span></a>
            </ul>
        </li>
        
    

    <!-- Categories  -->
    
        <li class="dropdown">
            <a href="#" class="ripple-effect dropdown-toggle" data-toggle="dropdown">
                
                    <i class="material-icons sidebar-material-icons">chrome_reader_mode</i>
                
                分类
                <b class="caret"></b>
            </a>
            <ul class="dropdown-menu">
                <li>
                <a class="sidebar_archives-link" href="/categories/android/">android<span class="sidebar_archives-count">2</span></a></li><li><a class="sidebar_archives-link" href="/categories/java/">java<span class="sidebar_archives-count">18</span></a></li><li><a class="sidebar_archives-link" href="/categories/mysql/">mysql<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/categories/weex/">weex<span class="sidebar_archives-count">1</span></a>
            </ul>
        </li>
        
            <li class="divider"></li>
        
    

    <!-- Pages  -->
    
        <li>
            <a href="/about" title="关于我">
                
                    <i class="material-icons sidebar-material-icons">person</i>
                
                关于我
            </a>
        </li>
        
    

    <!-- Article Number  -->
    
</ul>


        <!-- Sidebar Footer -->
        <!--
I'm glad you use this theme, the development is no so easy, I hope you can keep the copyright, I will thank you so much.
If you still want to delete the copyrights, could you still retain the first one? Which namely "Theme Material"
It will not impact the appearance and can give developers a lot of support :)

很高兴您使用并喜欢该主题，开发不易 十分谢谢与希望您可以保留一下版权声明。
如果您仍然想删除的话 能否只保留第一项呢？即 "Theme Material"
它不会影响美观并可以给开发者很大的支持和动力。 :)
-->

<!-- Sidebar Divider -->

    <div class="sidebar-divider"></div>


<!-- Theme Material -->

    <a href="https://github.com/viosey/hexo-theme-material"  class="sidebar-footer-text-a" target="_blank">
        <div class="sidebar-text mdl-button mdl-js-button mdl-js-ripple-effect sidebar-footer-text-div" data-upgraded=",MaterialButton,MaterialRipple">
            主题 - Material
            <span class="sidebar-badge badge-circle">i</span>
        </div>
    </a>


<!-- Help & Support -->
<!--

-->

<!-- Feedback -->
<!--

-->

<!-- About Theme -->
<!--

    <a href="https://blog.viosey.com/index.php/Material.html" target="_blank" class="sidebar-footer-text-a">
        <div class="sidebar-text mdl-button mdl-js-button mdl-js-ripple-effect sidebar-footer-text-div" data-upgraded=",MaterialButton,MaterialRipple">
             sidebar.about_theme
            <span class="mdl-button__ripple-container"><span class="mdl-ripple"></span></span></div>
    </a>

-->

    </div>

    <!-- Sidebar Image -->
    

</aside>

                    

                    
                        <!-- Footer Top Button -->
                        <div id="back-to-top" class="toTop-wrap">
    <a href="#top" class="toTop">
        <i class="material-icons footer_top-i">expand_less</i>
    </a>
</div>

                    

                    <!--Footer-->
<footer class="mdl-mini-footer" id="bottom">
    
        <!-- Paradox Footer Left Section -->
        <div class="mdl-mini-footer--left-section sns-list">
    <!-- Twitter -->
    

    <!-- Facebook -->
    

    <!-- Google + -->
    

    <!-- Weibo -->
    

    <!-- Instagram -->
    

    <!-- Tumblr -->
    

    <!-- Github -->
    
        <a href="https://github.com/xinwii" target="_blank">
            <button class="mdl-mini-footer--social-btn social-btn footer-sns-github">
                <span class="visuallyhidden">Github</span>
            </button><!--
     --></a>
    

    <!-- LinkedIn -->
    

    <!-- Zhihu -->
    

    <!-- Bilibili -->
    

    <!-- Telegram -->
    

    <!-- V2EX -->
    

    <!-- Segmentfault -->
    

    <p>Hosted by <a href="https://pages.coding.me" style="font-weight: bold">Coding Pages</a></p>
</div>


        <!--Copyright-->
        <div id="copyright">
            Copyright&nbsp;©&nbsp;<span year></span>&nbsp;android开发者
            
        </div>

        <!-- Paradox Footer Right Section -->

        <!--
        I am glad you use this theme, the development is no so easy, I hope you can keep the copyright.
        It will not impact the appearance and can give developers a lot of support :)

        很高兴您使用该主题，开发不易，希望您可以保留一下版权声明。
        它不会影响美观并可以给开发者很大的支持。 :)
        -->

        <div class="mdl-mini-footer--right-section">
            <div>
                <div class="footer-develop-div">Powered by Hexo</div>
                <div class="footer-develop-div">Theme - Material</div>
            </div>
        </div>
    
</footer>


                    <!-- Import JS File -->

    <script>lsloader.load("lazyload_js","/js/lazyload.min.js?1BcfzuNXqV+ntF6gq+5X3Q==", true)</script>



    <script>lsloader.load("js_js","/js/js.min.js?V/53wGualMuiPM3xoetD5Q==", true)</script>



    <script>lsloader.load("np_js","/js/nprogress.js?pl3Qhb9lvqR1FlyLUna1Yw==", true)</script>


<script type="text/ls-javascript" id="NProgress-script">
    NProgress.configure({
        showSpinner: true
    });
    NProgress.start();
    $('#nprogress .bar').css({
        'background': '#29d'
    });
    $('#nprogress .peg').css({
        'box-shadow': '0 0 10px #29d, 0 0 15px #29d'
    });
    $('#nprogress .spinner-icon').css({
        'border-top-color': '#29d',
        'border-left-color': '#29d'
    });
    setTimeout(function() {
        NProgress.done();
        $('.fade').removeClass('out');
    }, 800);
</script>





    <!-- Leancloud -->
    <script src="https://cdn1.lncld.net/static/js/av-core-mini-0.6.1.js"></script>
    <script>
        AV.initialize('vEOpfYrMUTPxez4tOTNQJv9A-gzGzoHsz', 'qlbEzWd9EJ3vHa07eHpWPIVU');
    </script>
    <script type="text/ls-javascript" id="leancloud-views-script">
    function showTime(Counter) {
        var query = new AV.Query(Counter);
        $('.leancloud-views_num').each(function() {
            var url = $(this).attr('id').trim();
            query.equalTo('url', url);
            query.find({
                success: function(results) {
                    if (results.length === 0) {
                        var content = '0 ' + $(document.getElementById(url)).text();
                        $(document.getElementById(url)).text(content);
                        return;
                    }
                    for (var i = 0; i < results.length; i++) {
                        var object = results[i];
                        var content = object.get('time') + ' ' + $(document.getElementById(url)).text();
                        $(document.getElementById(url)).text(content);
                    }
                },
                error: function(object, error) {
                    console.log('Error: ' + error.code + ' ' + error.message);
                }
            });
        });
    }

    function addCount(Counter) {
      var Counter = AV.Object.extend('Counter');
      url = $('.leancloud-views_num').attr('id').trim();
      title = $('.leancloud-views_num').attr('data-flag-title').trim();
      var query = new AV.Query(Counter);
      query.equalTo('url', url);
      query.find({
          success: function(results) {
            if (results.length > 0) {
                var counter = results[0];
                counter.fetchWhenSave(true);
                counter.increment('time');
                counter.save(null, {
                    success: function(counter) {
                        var content =  counter.get('time') + ' ' + $(document.getElementById(url)).text();
                        $(document.getElementById(url)).text(content);
                    },
                    error: function(counter, error) {
                        console.log('Failed to save Visitor num, with error message: ' + error.message);
                    }
                });
            } else {
              var newcounter = new Counter();
              newcounter.set('title', title);
              newcounter.set('url', url);
              newcounter.set('time', 1);
              newcounter.save(null, {
                  success: function(newcounter) {
                      console.log('newcounter.get(\'time\')='+newcounter.get('time'));
                      var content = newcounter.get('time') + ' ' + $(document.getElementById(url)).text();
                      $(document.getElementById(url)).text(content);
                  },
                  error: function(newcounter, error) {
                      console.log('Failed to create');
                  }
              });
            }
        },
        error: function(error) {
            console.log('Error:' + error.code + ' ' + error.message);
        }
      });
    }
    $(function() {
        var Counter = AV.Object.extend('Counter');
        if ($('.leancloud-views_num').length === 1) {
            addCount(Counter);
        } else if ($('.post-title-link').length > 1) {
            showTime(Counter);
        }
    });
</script>






   





<!-- UC Browser Compatible -->
<script>
	var agent = navigator.userAgent.toLowerCase();
	if(agent.indexOf('ucbrowser')>0) {
		document.write('<link rel="stylesheet" href="/css/uc.css">');
	   alert('由于 UC 浏览器使用极旧的内核，而本网站使用了一些新的特性。\n为了您能更好的浏览，推荐使用 Chrome 或 Firefox 浏览器。');
	}
</script>

<!-- Import prettify js  -->



<!-- Window Load -->
<!-- add class for prettify -->
<script type="text/ls-javascript" id="window-load">
    $(window).on('load', function() {
        // Post_Toc parent position fixed
        $('.post-toc-wrap').parent('.mdl-menu__container').css('position', 'fixed');
    });

    
    
</script>

<!-- MathJax Load-->


<!-- Bing Background -->


<script type="text/ls-javascript" id="lazy-load">
    // Offer LazyLoad
    queue.offer(function(){
        $('.lazy').lazyload({
            effect : 'show'
        });
    });

    // Start Queue
    $(document).ready(function(){
        setInterval(function(){
            queue.execNext();
        },200);
    });
</script>

<!-- Custom Footer -->



<script>
    var copyrightNow = new Date().getFullYear();
    var textContent = document.querySelector('span[year]')

    copyrightSince = 2015;
    if (copyrightSince === copyrightNow||copyrightSince === 0000) {
        textContent.textContent = copyrightNow
    } else {
        textContent.textContent = copyrightSince + ' - ' + copyrightNow
    }

    (function(){
        var scriptList = document.querySelectorAll('script[type="text/ls-javascript"]')

        for (var i = 0; i < scriptList.length; ++i) {
            var item = scriptList[i];
            lsloader.runInlineScript(item.id,item.id);
        }
    })()
console.log('\n %c © Material Theme | Version: 1.5.2 | https://github.com/viosey/hexo-theme-material %c \n', 'color:#455a64;background:#e0e0e0;padding:5px 0;border-top-left-radius:5px;border-bottom-left-radius:5px;', 'color:#455a64;background:#e0e0e0;padding:5px 0;border-top-right-radius:5px;border-bottom-right-radius:5px;');
</script>

                </main>
            </div>
        <script src="/live2dw/lib/L2Dwidget.min.js?0c58a1486de42ac6cc1c59c7d98ae887"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","model":{"scale":1,"hHeadPos":0.5,"vHeadPos":0.618,"jsonPath":"/live2dw/assets/z16.model.json"},"display":{"superSample":2,"width":150,"height":300,"position":"right","hOffset":0,"vOffset":-20},"mobile":{"show":true,"scale":0.1},"react":{"opacityDefault":0.7,"opacityOnHover":0.2}});</script></body>
    
</html>
